// utils/request.js
const ApiConfig = require('../config/api-config.js');

// 正在刷新 token 的 Promise，避免重复请求
let refreshingPromise = null;

/**
 * 核心请求函数（async/await 版）
 * @param {Object} options - wx.request 的配置项
 * @returns {Promise<any>}
 */
async function request(options) {
  const token = wx.getStorageSync(ApiConfig.tokenkeys.access);

  // 构造 header
  const header = {
    'Authorization': token ? `Bearer ${token}` : '',
    'Content-Type': 'application/json',
    ...options.header
  };

  try {
    const res = await wxRequest({
      ...options,
      header
    });

    if (res.statusCode === 401) {
      // Token 失效，尝试刷新
      try {
        await refreshToken(); // 等待刷新完成
        // 刷新成功后，重新发起原请求（只重试一次）
        return await request(options);
      } catch (refreshError) {
        console.error('Token 刷新失败:', refreshError);
        clearTokens();
        wx.showToast({
          title: '登录已过期，请重新登录',
          icon: 'none',
          duration: 2000,
          complete: () => {
            // 可选：跳转到登录页
            // wx.navigateTo({ url: '/pages/login/login' });
          }
        });
        throw new Error('Token expired');
      }
    } else if (res.statusCode >= 200 && res.statusCode < 300) {
      return res.data;
    } else {
      const message = res.data?.message || `请求失败: ${res.statusCode}`;
      wx.showToast({ title: message, icon: 'none' });
      throw res; // 抛出原始响应以便调用方处理
    }
  } catch (err) {
    // 网络错误或超时
    const message = err.errMsg?.includes('timeout') ? '请求超时' : '网络错误';
    wx.showToast({ title: message, icon: 'none' });
    throw err;
  }
}

/**
 * 封装 wx.request 为 Promise
 * @param {Object} options
 * @returns {Promise}
 */
function wxRequest(options) {
  return new Promise((resolve, reject) => {
    wx.request({
      ...options,
      success: resolve,
      fail: reject
    });
  });
}

/**
 * 刷新 Token（支持防重入）
 * @returns {Promise<string>} 新的 access token
 */
async function refreshToken() {
  if (refreshingPromise) {
    return refreshingPromise; // 复用正在进行的刷新
  }

  const refreshTokenValue = wx.getStorageSync(ApiConfig.tokenkeys.refresh);
  if (!refreshTokenValue) {
    throw new Error('No refresh token');
  }

  refreshingPromise = (async () => {
    try {
      const res = await wxRequest({
        url: ApiConfig.server.baseUrl + ApiConfig.endpoints.refreshToken,
        method: 'POST',
        data: { refreshToken: refreshTokenValue }, // 根据后端调整字段名
        header: {
          'Content-Type': 'application/json'
        }
      });

      if (res.statusCode === 200 && res.data?.code === 200) {
        const { token: newAccessToken, refreshToken: newRefreshToken } = res.data.data;
        wx.setStorageSync(ApiConfig.tokenkeys.access, newAccessToken);
        if (newRefreshToken) {
          wx.setStorageSync(ApiConfig.tokenkeys.refresh, newRefreshToken);
        }
        return newAccessToken;
      } else {
        throw res; // 视为刷新失败
      }
    } finally {
      // 无论成功失败，都要清除 refreshingPromise 引用
      refreshingPromise = null;
    }
  })();

  return refreshingPromise;
}

/**
 * 清除所有 Token
 */
function clearTokens() {
  wx.removeStorageSync(ApiConfig.tokenkeys.access);
  wx.removeStorageSync(ApiConfig.tokenkeys.refresh);
  const app = getApp();
  if (app && app.globalData) {
    app.globalData.hasToken = false;
  }
}

// 便捷方法
async function get(url, data) {
  return request({ url, method: 'GET', data });
}

async function post(url, data) {
  return request({ url, method: 'POST', data });
}

module.exports = { request, get, post };